/**************************************
 * File: GCPtr.h
 * Author: Osborne McGraw-Hill
 * Modified by: Anders "Saasen" Stensaas
 *				Stig Magnus Halvorsen
 *				Peder Thorup
 * 
 * Description: Extracted from Osborne
 *				McGraw-Hill's gc.h. A
 *				single threaded Garbage Collector
 *
 * Source:
 *	http://www.devarticles.com/c/a/Cplusplus/A-Simple-Garbage-Collector-for-C-plus-plus/3/
 *
 ************************************/

#ifndef GCPTR_H // inclusion guard
#define GCPTR_H

#include "Logger.h"
#include "GCInfo.h"
#include "Iter.h"

#include <string>
#include <list>
#include <typeinfo>
#include <cstdlib>

// To disable logging, change the trigger level to "WARN"
// at the end of this document.

// GCPtr implements a pointer type that uses
// garbage collection to release unused memory.
// A GCPtr must only be used to point to memory
// that was dynamically allocated using new.
// When used to refer to an allocated array,
// specify the array size.

template <class T, int size=0> class GCPtr {
	// addr points to the allocated memory to which
	// this GCPtr pointer currently points.
	T *addr;

	// isArray is true if this GCPtr points
	// to an allocated array. It is false
	// otherwise.
	bool isArray;

	// If this GCPtr is pointing to an allocated
	// array, then arraySize contains its size.
	unsigned arraySize;

	// Return an iterator to pointer info in gclist.
	typename std::list<GCInfo>::iterator findPtrInfo(T *ptr);

	// The log object, initialized in the constructor of the cpp file

public:
	// Define an iterator type for GCPtr<T>.
	typedef Iter<T> GCiterator;

	// Construct both initialized and uninitialized objects.
	GCPtr(T *t=NULL);

	// Copy constructor.
	GCPtr(const GCPtr &ob);

	// Destructor for GCPTr.
	~GCPtr();

	// Collect garbage. Returns true if at least
	// one object was freed.
	static bool collect();

	// Overload assignment of pointer to GCPtr.
	T *operator=(T *t);

	// Overload assignment of GCPtr to GCPtr.
	GCPtr &operator=(GCPtr &rv);

	// Return a reference to the object pointed
	// to by this GCPtr.
	T &operator*();

	// Return the address being pointed to.
	T *operator->();

	// Return a reference to the object at the
	// index specified by i.
	T &operator[](int i);

	// Conversion function to T *.
	operator T *();

	// Return an Iter to the start of the allocated memory.  
	Iter<T> begin();

	// Return an Iter to one past the end of an allocated array.
	Iter<T> end();

	// Return the size of gclist for this type
	// of GCPtr.
	static int gclistSize();

	// A utility function that displays gclist.
	static void showlist();

	// Clear remaining memory when program exits.
	static void shutdown();
};

// Initialize the static variables, it won't work without it
// as we have splitted the templates in several files.
template <class T, int size> bool GCPtr<T, size>::collect();
template <class T, int size> int GCPtr<T, size>::gclistSize();
template <class T, int size> void GCPtr<T, size>::showlist();
template <class T, int size> void GCPtr<T, size>::shutdown();

// To disable logging, change the trigger level to "WARN"

// Include the cpp file, it won't work without it as we have
// splitted the templates.
#include "GCPtr.cpp"

#endif // end inclusion guard